#!/sw/bin/python
import unittest,Board

class InitTest(unittest.TestCase):
	"""Performs all relevent tests on an empty board."""
	def setUp(self):
		"""Creates an empty board."""
		self.test_board=Board.Board()

	def testStatus(self):
		"""Tests status() for an empty board."""
		result,avatar=self.test_board.status()
		self.failUnless(result==0 and avatar==None,'status() did not work on an empty board; 0!= %s; None!=%s' % (result,avatar))

	def testMoveCount(self):
		"""Tests moveCount() on an empty board."""
		move_count=self.test_board.moveCount()
		self.failUnlessEqual(move_count,0,'move count should be 0, not %s' % move_count)

	def testCanRollback(self):
		"""Tests canRollback() on an empty board."""
		self.failUnless(self.test_board.canRollback()==0,'canRollback() did not work on an empty board')

	def testRollbackMove(self):
		"""Test rollbackMove() on an empty board."""
		self.failUnlessRaises(Board.BoardError,self.test_board.rollbackMove)

	def testSize(self):
		"""Tests size() on an empty board.

		NOT LARGER BOARD COMPATIBLE!
		
		"""
		board_size=self.test_board.size()
		self.failUnlessEqual(board_size,(3,3),'`Board size not correct')

	def testCopy(self):
		"""Tests copy() on an empty board."""
		board_copy=self.test_board.copy()
		self.failUnless(board_copy.board==self.test_board.board and board_copy.move_count==self.test_board.move_count and board_copy.moves==self.test_board.moves,'copy() did not work on an empty board')



class MovesTest(unittest.TestCase):
	"""Collection of tests on moves."""
	def setUp(self):
		self.test_board=Board.Board()

	def testSimpleMove(self):
		"""Tests a single move."""
		self.test_board.makeMove((1,1),'X')
		self.failUnless(self.test_board.board[1][1]=='X' and self.test_board.moveCount()==1,'Move failed')

	def testMultipleMoves(self):
		"""Tests making two moves."""
		self.test_board.makeMove((0,2),'X')
		self.test_board.makeMove((1,1),'O')
		self.failUnless(self.test_board.board[0][2]=='X' and self.test_board.board[1][1]=='O' and self.test_board.moveCount()==2,'Multiple moves failed')

	def testIllegalMove(self):
		"""Tests making an illegal move."""
		self.test_board.makeMove((0,0),'X')
		self.failUnlessRaises(Board.BoardError,self.test_board.makeMove,(0,0),'O')

	def testCanRollback(self):
		"""Tests canRollback()."""
		self.test_board.makeMove((0,0),'X')
		self.failUnless(self.test_board.canRollback()==1,'canRollback() isn\'t working')

	def testRollback(self):
		"""Tests rollbackMove()."""
		self.test_board.makeMove((0,0),'X')
		self.test_board.rollbackMove()
		self.failUnless(self.test_board.board[0][0]==None and self.test_board.moveCount()==0 and self.test_board.canRollback()==0,'rollbackMove() is broken')



class StatusTest(unittest.TestCase):
	"""Tests status()."""
	def setUp(self):
		self.test_board=Board.Board()

	def testRow1(self):
		self.test_board.makeMove((0,0),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((1,1),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((0,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((2,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((0,2),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a row 1 win failed')

	def testRow2(self):
		self.test_board.makeMove((1,0),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((2,2),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((2,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((1,2),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a row 2 win failed')

	def testRow3(self):
		self.test_board.makeMove((2,0),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((1,1),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((2,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,2),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a row 3 win failed')

	def testCol1(self):
		self.test_board.makeMove((0,0),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((0,2),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,0),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,0),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a col 1 win failed')

	def testCol2(self):
		self.test_board.makeMove((0,1),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((0,2),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,0),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,1),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a col 2 win failed')

	def testCol3(self):
		self.test_board.makeMove((0,2),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((0,0),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,2),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,2),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a col 3 win failed')

	def testDiagUL(self):
		self.test_board.makeMove((0,0),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((0,2),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,2),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a diagnoal (upper-left to lower-right) win failed')

	def testDiagUR(self):
		self.test_board.makeMove((0,2),'X')
		statusx1=self.test_board.status()
		self.test_board.makeMove((0,0),'O')
		statuso1=self.test_board.status()
		self.test_board.makeMove((1,1),'X')
		statusx2=self.test_board.status()
		self.test_board.makeMove((0,1),'O')
		statuso2=self.test_board.status()
		self.test_board.makeMove((2,0),'X')
		statusx3=self.test_board.status()
		self.failUnless(statusx1==(0,None) and statuso1==(0,None) and statusx2==(0,None) and statuso2==(0,None) and statusx3==(1,'X'),'Check for a diagonal (upper-right to lower-left) win failed')

	def testCatsGame(self):
		self.test_board.makeMove((1,1),'X')
		self.test_board.makeMove((0,0),'O')
		self.test_board.makeMove((0,2),'X')
		self.test_board.makeMove((2,0),'O')
		self.test_board.makeMove((1,0),'X')
		self.test_board.makeMove((1,2),'O')
		self.test_board.makeMove((2,1),'X')
		self.test_board.makeMove((0,1),'O')
		result=self.test_board.status()
		self.failUnless(result==(-1,None))



def suite():
	empty_board_suite=unittest.MakeSuite(InitTest,'test')
	move_suite=unittest.MakeSuite(MovesTest,'test')
	status_suite=unittest.MakeSuite(StatusTest,'test')
	return unittest.TestSuite((empty_board_suite,move_suite,status_test))



if __name__=='__main__':
	unittest.main()

